home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / glibc-1.09 / glibc-1 / glibc-1.09.1 / sysdeps / standalone / i386 / start.S
Encoding:
Text File  |  1994-08-25  |  9.6 KB  |  324 lines

  1. /* Copyright (C) 1994 Free Software Foundation, Inc.
  2.    Contributed by Joel Sherrill (jsherril@redstone-emh2.army.mil),
  3.      On-Line Applications Research Corporation.
  4.  
  5. This file is part of the GNU C Library.
  6.  
  7. The GNU C Library is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU Library General Public License as
  9. published by the Free Software Foundation; either version 2 of the
  10. License, or (at your option) any later version.
  11.  
  12. The GNU C Library is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. Library General Public License for more details.
  16.  
  17. You should have received a copy of the GNU Library General Public
  18. License along with the GNU C Library; see the file COPYING.LIB.  If
  19. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  20. Cambridge, MA 02139, USA.  */
  21.  
  22. /*  entry.s
  23.  *
  24.  *  This file contains the entry point for the application.
  25.  *  The name of this entry point is compiler dependent.
  26.  *  It jumps to the BSP which is responsible for performing
  27.  *  all initialization.
  28.  *
  29.  */
  30.  
  31.         .data
  32.         .global  _Do_Load_IDT
  33.         .global  _Do_Load_GDT
  34.  
  35.         .text
  36.           .global  start                  # GNU default entry point
  37.         .global  _establish_stack
  38.  
  39.         .global   _bsp_start
  40.         .global   _load_segments
  41.         .global   __exit
  42.  
  43. start:
  44.         nop
  45.         cli                             # DISABLE INTERRUPTS!!!
  46. #
  47. #  Load the segment registers
  48. #
  49. #  NOTE: Upon return, gs will contain the segment descriptor for
  50. #        a segment which maps directly to all of physical memory.
  51. #
  52.         jmp     _load_segments          # load board dependent segments
  53.  
  54. #
  55. #  Set up the stack
  56. #
  57.  
  58. _establish_stack:
  59.  
  60.         movl    $stack_end,%esp         # set stack pointer
  61.         movl    $stack_end,%ebp         # set base pointer
  62.  
  63. #
  64. #  Zero out the BSS segment
  65. #
  66. zero_bss:
  67.         cld                             # make direction flag count up
  68.         movl    $_end,%ecx              # find end of .bss
  69.         movl    $_bss_start,%edi        # edi = beginning of .bss
  70.         subl    %edi,%ecx               # ecx = size of .bss in bytes
  71.         shrl    $2,%ecx                 # size of .bss in longs
  72.         xorl    %eax,%eax               # value to clear out memory
  73.         repne                           # while ecx != 0
  74.         stosl                           #   clear a long in the bss
  75.  
  76. #
  77. #  Set the C heap information for malloc
  78. #
  79.         movl    $heap_size,___C_heap_size    # set ___C_heap_size
  80.         movl    $heap_memory,___C_heap_start # set ___C_heap_start
  81.  
  82. #
  83. #  Copy the Global Descriptor Table to our space
  84. #
  85.  
  86.         sgdt    _Original_GDTR          # save original GDT
  87.         movzwl  _Original_GDTR_limit,%ecx # size of GDT in bytes; limit 
  88.                                           #   is 8192 entries * 8 bytes per
  89.  
  90.         # make ds:esi point to the original GDT
  91.  
  92.         movl    _Original_GDTR_base,%esi
  93.         push    %ds                     # save ds
  94.         movw    %gs,%ax
  95.         movw    %ax,%ds 
  96.  
  97.         # make es:edi point to the new (our copy) GDT
  98.         movl    $_Global_descriptor_table,%edi
  99.  
  100.         rep
  101.         movsb                            # copy the GDT (ds:esi -> es:edi)
  102.  
  103.         pop     %ds                      # restore ds
  104.       
  105.         # Build and load new contents of GDTR
  106.         movw    _Original_GDTR_limit,%ecx # set new limit
  107.         movw    %cx,_New_GDTR_limit
  108.  
  109.         push    $_Global_descriptor_table
  110.         push    %es
  111.         call    _Logical_to_physical
  112.         addl    $6,%esp
  113.         movl    %eax,_New_GDTR_base      # set new base
  114.  
  115.         cmpb    $0,_Do_Load_GDT          # Should the new GDT be loaded?
  116.         je      no_gdt_load              # NO, then branch
  117.         lgdt    _New_GDTR                # load the new GDT
  118. no_gdt_load:
  119.  
  120. #
  121. #  Copy the Interrupt Descriptor Table to our space
  122. #
  123.  
  124.         sidt    _Original_IDTR          # save original IDT
  125.         movzwl  _Original_IDTR_limit,%ecx # size of IDT in bytes; limit
  126.                                           #   is 256 entries * 8 bytes per
  127.  
  128.  
  129.         # make ds:esi point to the original IDT
  130.         movl    _Original_IDTR_base,%esi
  131.  
  132.         push    %ds                     # save ds
  133.         movw    %gs,%ax
  134.         movw    %ax,%ds 
  135.  
  136.         # make es:edi point to the new (our copy) IDT
  137.         movl    $_Interrupt_descriptor_table,%edi
  138.  
  139.         rep
  140.         movsb                            # copy the IDT (ds:esi -> es:edi)
  141.         pop     %ds                      # restore ds
  142.  
  143.         # Build and load new contents of IDTR
  144.         movw    _Original_IDTR_limit,%ecx # set new limit
  145.         movw    %cx,_New_IDTR_limit
  146.  
  147.         push    $_Interrupt_descriptor_table
  148.         push    %es
  149.         call    _Logical_to_physical
  150.         addl    $6,%esp
  151.         movl    %eax,_New_IDTR_base      # set new base
  152.  
  153.         cmpb    $0,_Do_Load_IDT          # Should the new IDT be loaded?
  154.         je      no_idt_load              # NO, then branch
  155.         lidt    _New_IDTR                # load the new IDT
  156. no_idt_load:
  157.  
  158. #
  159. #  Initialize the i387.
  160. #
  161. #  Using the NO WAIT form of the instruction insures that if
  162. #  it is not present the board will not lock up or get an
  163. #  exception.
  164. #
  165.  
  166.         fninit                           # MUST USE NO-WAIT FORM
  167.  
  168.         call    __Board_Initialize       # initialize the board
  169.  
  170.         pushl   $0                       # envp = NULL 
  171.         pushl   $0                       # argv = NULL 
  172.         pushl   $0                       # argc = NULL 
  173.         call    ___libc_init             # initialize the library and
  174.                                          #   call main
  175.         addl    $12,%esp
  176.  
  177.         pushl   $0                       # argc = NULL 
  178.         call    __exit                   # call the Board specific exit
  179.         addl     $4,%esp
  180.  
  181. #
  182. #  Clean up
  183. #
  184.  
  185.  
  186.         .global  _Bsp_cleanup
  187.  
  188.         .global   _return_to_monitor
  189.  
  190. _Bsp_cleanup:
  191.         cmpb    $0,_Do_Load_IDT          # Was the new IDT loaded?
  192.         je      no_idt_restore           # NO, then branch
  193.         lidt    _Original_IDTR           # restore the new IDT
  194. no_idt_restore:
  195.  
  196.         cmpb    $0,_Do_Load_GDT          # Was the new GDT loaded?
  197.         je      no_gdt_restore           # NO, then branch
  198.         lgdt    _Original_GDTR           # restore the new GDT
  199. no_gdt_restore:
  200.         jmp     _return_to_monitor
  201.  
  202. #
  203. #  void *Logical_to_physical( 
  204. #     rtems_unsigned16  segment,
  205. #     void             *address
  206. #  );
  207. #
  208. #  Returns thirty-two bit physical address for segment:address.
  209. #
  210.  
  211.         .global  _Logical_to_physical
  212.  
  213. .set SEGMENT_ARG, 4
  214. .set ADDRESS_ARG, 8
  215.  
  216. _Logical_to_physical:
  217.  
  218.         xorl    %eax,%eax                # clear eax
  219.         movzwl  SEGMENT_ARG(%esp),%ecx   # ecx = segment value
  220.         movl    $_Global_descriptor_table,%edx # edx = address of our GDT
  221.         addl    %ecx,%edx                # edx = address of desired entry
  222.         movb    7(%edx),%ah              # ah = base 31:24
  223.         movb    4(%edx),%al              # al = base 23:16
  224.         shll    $16,%eax                 # move ax into correct bits
  225.         movw    2(%edx),%ax              # ax = base 0:15
  226.         movl    ADDRESS_ARG(%esp),%ecx   # ecx = address to convert
  227.         addl    %eax,%ecx                # ecx = physical address equivalent
  228.         movl    %ecx,%eax                # eax = ecx
  229.         ret
  230.        
  231. #
  232. #  void *Physical_to_logical( 
  233. #     rtems_unsigned16  segment,
  234. #     void             *address
  235. #  );
  236. #
  237. #  Returns thirty-two bit physical address for segment:address.
  238. #
  239.  
  240.         .global  _Physical_to_logical
  241.  
  242. #.set SEGMENT_ARG, 4
  243. #.set ADDRESS_ARG, 8   -- use sets from above
  244.  
  245. _Physical_to_logical:
  246.  
  247.         xorl    %eax,%eax                # clear eax
  248.         movzwl  SEGMENT_ARG(%esp),%ecx   # ecx = segment value
  249.         movl    $_Global_descriptor_table,%edx # edx = address of our GDT
  250.         addl    %ecx,%edx                # edx = address of desired entry
  251.         movb    7(%edx),%ah              # ah = base 31:24
  252.         movb    4(%edx),%al              # al = base 23:16
  253.         shll    $16,%eax                 # move ax into correct bits
  254.         movw    2(%edx),%ax              # ax = base 0:15
  255.         movl    ADDRESS_ARG(%esp),%ecx   # ecx = address to convert
  256.         subl    %eax,%ecx                # ecx = logical address equivalent
  257.         movl    %ecx,%eax                # eax = ecx
  258.         ret
  259.        
  260.  
  261. /*
  262.  *  Data Declarations.  Start with a macro which helps declare space.
  263.  */
  264.  
  265.         .bss
  266.  
  267. #define DECLARE_SPACE(_name,_space,_align) \
  268.           .globl   _name ; \
  269.           .align   _align ; \
  270. _name##:  .space _space
  271.  
  272. #define DECLARE_LABEL(_name) \
  273.           .globl   _name ; \
  274. _name##:  
  275.  
  276. #define DECLARE_PTR(_name) DECLARE_SPACE(_name,4,2)
  277. #define DECLARE_U32(_name) DECLARE_SPACE(_name,4,2)
  278. #define DECLARE_U16(_name) DECLARE_SPACE(_name,2,1)
  279.  
  280. /*
  281.  *  Require environment stuff
  282.  */
  283.  
  284. DECLARE_LABEL(_environ)
  285. DECLARE_PTR(environ)
  286.  
  287. DECLARE_LABEL(_errno)
  288. DECLARE_U32(errno)
  289.  
  290. /* 
  291.  *  Miscellaneous Variables used to restore the CPU state.
  292.  *
  293.  *  Start with a macro to declare the space for the contents of
  294.  *  a Descriptor Table register.
  295.  */
  296.  
  297. #define DECLARE_DTR_SPACE(_name) \
  298.           .global   _name ; \
  299.           .align    4 ; \
  300. _name##:  ; \
  301. _name##_limit:  .space 2  ; \
  302. _name##_base:   .space 4
  303.  
  304. DECLARE_SPACE(_Interrupt_descriptor_table,256*8,4)
  305. DECLARE_SPACE(_Global_descriptor_table,8192*8,4)
  306.  
  307. DECLARE_DTR_SPACE(_Original_IDTR)
  308. DECLARE_DTR_SPACE(_New_IDTR)
  309. DECLARE_DTR_SPACE(_Original_GDTR)
  310. DECLARE_DTR_SPACE(_New_GDTR)
  311.  
  312. DECLARE_SPACE(_Physical_base_of_ds,4,4)
  313. DECLARE_SPACE(_Physical_base_of_cs,4,4)
  314.  
  315. /*
  316.  *  Stack Size and Space
  317.  */
  318.  
  319.         .set stack_size, 0x20000
  320.  
  321. DECLARE_SPACE(stack_memory,stack_size,4)
  322. DECLARE_LABEL(stack_end)
  323.  
  324.